/*
 *    Copyright 2022 The DSMS Authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.dsms.common.interceptor;

import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson2.JSON;
import com.dsms.common.model.DatabaseFieldSubBO;
import com.dsms.common.util.DatabaseFieldUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class MybatisInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        Object parameter = invocation.getArgs()[1];

        if (parameter == null) {
            return invocation.proceed();
        }

        Object object = null;
        MapperMethod.ParamMap objectMap = null;

        if (SqlCommandType.INSERT == sqlCommandType) {
            object = parameter;
        } else if (SqlCommandType.UPDATE == sqlCommandType) {
            objectMap = (MapperMethod.ParamMap) parameter;
            object = objectMap.get("et");
        }
        if (object != null) {
            for (DatabaseFieldSubBO databaseFieldSubBO : DatabaseFieldUtil.databaseFieldSubList) {
                if (databaseFieldSubBO.getClazz().equals(object.getClass()) || databaseFieldSubBO.getClazz().equals(object.getClass().getSuperclass())) {
                    subFieldValue(object, databaseFieldSubBO.getTableFieldName(), databaseFieldSubBO.getDatabaseLength());
                }
            }
        }

        return invocation.proceed();
    }

    boolean subFieldValue(Object object, String fieldName, int exceptLength) {
        Object fieldValue = ReflectUtil.getFieldValue(object, fieldName);
        if (String.valueOf(fieldValue).length() > exceptLength) {
            log.error("database field too long,field name:{},before object:{},", fieldName, JSON.toJSONString(object));
            String newVal = fieldValue == null ? "" : String.valueOf(fieldValue).substring(0, exceptLength);
            ReflectUtil.setFieldValue(object, fieldName, newVal);
            log.error("database field too long,field name:{},after object:{}", fieldName, JSON.toJSONString(object));
            return true;
        }

        return false;
    }

}